package cn.org.itool.common.utils;

import java.util.ArrayList;
import java.util.List;

public class TagParserUtil {
    private static class Token {
        enum Type {
            AND, OR, SYMBOL, EOF
        }

        Type type;
        String value;

        Token(Type type, String value) {
            this.type = type;
            this.value = value;
        }
    }

    private static class Lexer {
        private final String input;
        private int position;

        Lexer(String input) {
            this.input = input;
            this.position = 0;
        }

        Token nextToken() {
            while (position < input.length()) {
                char ch = input.charAt(position++);
                switch (ch) {
                    case ',':
                        return new Token(Token.Type.AND, ",");
                    case '|':
                        if (position < input.length() && input.charAt(position) == '|') {
                            position++;
                            return new Token(Token.Type.OR, "||");
                        }
                        break;
                    default:
                        if (check(ch)) {
                            StringBuilder sb = new StringBuilder();
                            sb.append(ch);
                            while (position < input.length() && check(input.charAt(position))) {
                                sb.append(input.charAt(position++));
                            }
                            return new Token(Token.Type.SYMBOL, sb.toString());
                        }
                        break;
                }
            }
            return new Token(Token.Type.EOF, "");
        }

        private boolean check(char ch) {
            return Character.isLetter(ch) || Character.isDigit(ch);
        }
    }

    public static class Parser {
        private final Lexer lexer;
        private Token currentToken;

        Parser(String input) {
            this.lexer = new Lexer(input);
            this.currentToken = lexer.nextToken();
        }

        List<List<String>> parse() {
            List<List<String>> orExpressions = new ArrayList<>();
            List<String> andExpressions = new ArrayList<>();

            while (currentToken.type != Token.Type.EOF) {
                if (currentToken.type == Token.Type.SYMBOL) {
                    andExpressions.add(currentToken.value);
                    currentToken = lexer.nextToken();
                } else if (currentToken.type == Token.Type.AND) {
                    currentToken = lexer.nextToken();
                } else if (currentToken.type == Token.Type.OR) {
                    orExpressions.add(andExpressions);
                    andExpressions = new ArrayList<>();
                    currentToken = lexer.nextToken();
                }
            }

            if (!andExpressions.isEmpty()) {
                orExpressions.add(andExpressions);
            }

            return orExpressions;
        }
    }

}

